﻿using BlogApi.Data;
using BlogApi.Models;
using BlogApi.ModelsDto;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogApi.Services
{
    public class ArticleRepository:IArticleRepository
    {
        private readonly BlogDbContext _context;

        public ArticleRepository(BlogDbContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
        }
        public async Task<IEnumerable<Article>> GetArticlesAsync()
        {
            return await _context.Articles_table.OrderByDescending(item => item.CreateTime).ToListAsync();
        }
        public async Task<IEnumerable<Article>> GetArticlesByPageAsync(int pageSize, int pageIndex)
        {
            return await _context.Articles_table.OrderByDescending(item => item.CreateTime).Skip(pageSize * pageIndex).Take(pageSize).ToListAsync();
        }
        public async Task<IEnumerable<ArticleAndUserInfoDto>> SearchPublishedArticleByPage(string keyword, int pageSize, int pageIndex)
        {
            return await _context.Articles_table.Where(item => item.Status=="published"&&item.Title.ToLower().Contains(keyword.ToLower())).Skip(pageSize * pageIndex).Take(pageSize).Include(item => item.User).Select(m => new ArticleAndUserInfoDto()
            {
                Id = m.Id,
                AuthorId = m.UserId,
                UserImg = m.User.UserImageUrl,
                UserNickName = m.User.NickName,
                Title = m.Title,
                GoodCount = m.GoodNumber,
                BrowseCount = m.BrowseNumber,
                CommentCount = m.CommentNumber,
                PublishedDate = m.PublishedDate.ToString("yyyy-MM-dd")
            }).ToListAsync();
        }
        public async Task<Article> GetArticleAsync(Guid articleId)
        {
            if (articleId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(articleId));
            }
            return await _context.Articles_table.FirstOrDefaultAsync(item => item.Id == articleId);
        }
        public async Task<IEnumerable<Article>> GetUserArticlesByPageAsync(Guid userId, int pageSize, int pageIndex)
        {
            if (userId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(userId));
            }
            return await _context.Articles_table.Where(item => item.UserId == userId).Skip(pageSize * pageIndex).Take(pageSize).ToListAsync();
        }
        public async Task<IEnumerable<ArticleAndUserInfoDto>> GetArticleAndUserInfosByPageAsync(int pageSize, int pageIndex)
        {
            return await _context.Articles_table.Where(item=>item.Status=="published").OrderByDescending(item => item.PublishedDate).Skip(pageSize * pageIndex).Take(pageSize).Include(item => item.User).Select(m => new ArticleAndUserInfoDto()
            {
                Id = m.Id,
                AuthorId = m.UserId,
                UserImg = m.User.UserImageUrl,
                UserNickName = m.User.NickName,
                Title = m.Title,
                GoodCount = m.GoodNumber,
                BrowseCount = m.BrowseNumber,
                CommentCount = m.CommentNumber,
                PublishedDate = m.PublishedDate.ToString("yyyy-MM-dd")
            }).ToListAsync();
        }
        public async Task<ArticleAndUserInfoDto> GetArticleAndUserInfoDtoByArticleIdAsync(Guid articleId)
        {
            if (articleId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(articleId));
            }
            var articleDto = _context.Articles_table.Where(m => m.Id == articleId).Include(m => m.User).Select(m => new ArticleAndUserInfoDto()
            {
                Id = m.Id,
                AuthorId = m.UserId,
                UserImg = m.User.UserImageUrl,
                UserNickName = m.User.NickName,
                Title = m.Title,
                GoodCount = m.GoodNumber,
                BrowseCount = m.BrowseNumber,
                CommentCount = m.BrowseNumber,
                PublishedDate = m.PublishedDate.ToString("yyyy-MM-dd")
            }).FirstAsync();
            return await articleDto;
        }
        public async Task<IEnumerable<ArticleAndUserInfoDto>> GetArticleAndUserInfosByPageOrderByBrowseNumber(int pageSize, int pageIndex)
        {
            return await _context.Articles_table.Where(item => item.Status == "published").OrderByDescending(item=>item.BrowseNumber).Skip(pageSize * pageIndex).Take(pageSize).Include(item => item.User).Select(m => new ArticleAndUserInfoDto()
            {
                Id = m.Id,
                AuthorId = m.UserId,
                UserImg = m.User.UserImageUrl,
                UserNickName = m.User.NickName,
                Title = m.Title,
                GoodCount = m.GoodNumber,
                BrowseCount = m.BrowseNumber,
                CommentCount = m.CommentNumber,
                PublishedDate = m.PublishedDate.ToString("yyyy-MM-dd")
            }).ToListAsync();
        }
        public void AddArticle(Article article)
        {
            if (article == null)
            {
                throw new ArgumentNullException(nameof(article));
            }
            _context.Articles_table.Add(article);
        }
        public void UpdateArticle(Article article)
        {
            //由于数据库上下文会对实体进行跟踪 所以这句话可以不写
            //_context.Entry(article).State = EntityState.Modified;
        }
        public void DeleteArticle(Article article)
        {
            if (article == null)
            {
                throw new ArgumentNullException(nameof(article));
            }
            _context.Articles_table.Remove(article);
        }
        public async Task<bool> ArticleExistsAsync(Guid articleId)
        {
            if (articleId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(articleId));
            }
            return await _context.Articles_table.AnyAsync(item => item.Id == articleId);
        }
        public async Task<bool> SaveAsync()
        {
            return await _context.SaveChangesAsync() >= 0;
        }
        public async Task<IEnumerable<Article>> GetUserSpaceArticleByPageAsync(Guid userId, int pageSize, int pageIndex)
        {
            if (userId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(userId));
            }
            return await _context.Articles_table.Where(item => item.UserId == userId&&item.Status=="published").Skip(pageSize * pageIndex).Take(pageSize).ToListAsync();
        }
    }
}
